home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 8: LINUX Games / Linux Cubed Series 8 - LINUX Games.iso / games / muds / pennmush.000 / pennmush-1.50-p8-linux.tar / pennmush / bsd.c < prev    next >
C/C++ Source or Header  |  1993-04-21  |  55KB  |  2,428 lines

  1. /* bsd.c */
  2.  
  3. #include "copyright.h"
  4.  
  5. #include <stdio.h>
  6. #include <varargs.h>
  7. #include <sys/types.h>
  8. #include <sys/file.h>
  9. #include <sys/time.h>
  10. #include <signal.h>
  11. #include <sys/ioctl.h>
  12. #include <sys/wait.h>
  13. #include <fcntl.h>
  14. #include <sys/errno.h>
  15. #include <ctype.h>
  16. #include <sys/socket.h>
  17. #include <netinet/in.h>
  18. #include <netdb.h>
  19. #include <string.h>
  20. #include <sys/param.h>
  21. #ifdef HPUX
  22. #include <unistd.h>
  23. #endif
  24.  
  25. #include "config.h"
  26. #include "db.h"
  27. #include "interface.h"
  28. #include "externs.h"
  29. #include "globals.h"
  30. #include "help.h"
  31.  
  32. #ifdef MEM_CHECK
  33. #include "mem_check.h"
  34. #endif
  35.  
  36. #if (CHAT_SYSTEM >= 2)
  37. #include "chat.h"
  38. #endif
  39.  
  40. /* AIX, BSD 4.2, and maybe some others need these defined */
  41. #ifndef FD_ZERO
  42. #define fd_set int
  43. #define FD_ZERO(p)       (*p = 0)
  44. #define FD_SET(n,p)      (*p |= (1<<(n)))
  45. #define FD_CLR(n,p)      (*p &= ~(1<<(n)))
  46. #define FD_ISSET(n,p)    (*p & (1<<(n)))
  47. #endif                /* defines for AIX */
  48.  
  49. extern void rusage_stats();
  50.  
  51. extern dbref speaker;
  52. extern int errno;
  53. extern int reserved;
  54. int shutdown_flag = 0;
  55. extern dbref db_top;
  56.  
  57. #ifdef LOGIN_LIMIT
  58. static int login_number = 0;
  59. #endif                /* LOGIN_LIMIT */
  60. static int under_limit = 1;
  61.  
  62. char cf_motd_msg[BUFFER_LEN], cf_wizmotd_msg[BUFFER_LEN],
  63.      cf_downmotd_msg[BUFFER_LEN], cf_fullmotd_msg[BUFFER_LEN];
  64.  
  65. #ifdef AT_DOING
  66. static char poll[39];
  67. #endif
  68.  
  69. struct text_block {
  70.   int nchars;
  71.   struct text_block *nxt;
  72.   char *start;
  73.   char *buf;
  74. };
  75.  
  76. struct text_queue {
  77.   struct text_block *head;
  78.   struct text_block **tail;
  79. };
  80.  
  81. struct descriptor_data {
  82.   int descriptor;
  83.   int connected;
  84.   char addr[51];
  85.   dbref player;
  86.   char *output_prefix;
  87.   char *output_suffix;
  88.   int output_size;
  89.   struct text_queue output;
  90.   struct text_queue input;
  91.   char *raw_input;
  92.   char *raw_input_at;
  93.   long connected_at;
  94.   long last_time;
  95.   int quota;
  96.   int cmds;
  97.   int hide;
  98. #ifdef AT_DOING
  99.   char doing[40];
  100. #endif
  101.   struct sockaddr_in address;    /* added 3/6/90 SCG */
  102.   struct descriptor_data *next;
  103.   struct descriptor_data **prev;
  104. };
  105.  
  106. typedef struct descriptor_data DESC;
  107.  
  108. #define DESC_ITER_CONN(d) \
  109.         for(d = descriptor_list;(d);d=(d)->next) \
  110.       if((d)->connected)
  111.  
  112. #define Hidden(d)        ((d->hide == 1) && Can_Hide(d->player))
  113.  
  114. /* log file pointers */
  115. FILE *connlog_fp;
  116. FILE *checklog_fp;
  117. FILE *wizlog_fp;
  118. FILE *tracelog_fp;
  119. FILE *cmdlog_fp;
  120.  
  121. static const char *connect_fail = "Either that player does not exist, or has a different password.\n";
  122. static const char *create_fail = "Either there is already a player with that name, or that name is illegal.\n";
  123. static const char *flushed_message = "<Output Flushed>\n";
  124. static const char *shutdown_message = "Going down - Bye\n";
  125. static const char *asterisk_line =
  126.     "*****************************************************************";
  127.  
  128. struct descriptor_data *descriptor_list = 0;
  129.  
  130. static int sock;
  131. static int ndescriptors = 0;
  132. char ccom[BUFFER_LEN];
  133. dbref cplr;
  134.  
  135. void process_commands();
  136. void shovechars();
  137. void shutdownsock();
  138. struct descriptor_data *initializesock();
  139. void make_nonblocking();
  140. void freeqs();
  141. void welcome_user();
  142. int check_connect();
  143. void close_sockets();
  144. const char *hostname_convert();
  145. void dump_users();
  146.  
  147. #ifdef RWHO_SEND
  148. #ifdef FULL_RWHO
  149. void dump_rusers();
  150. #endif
  151. void rwho_update();
  152. #endif
  153.  
  154. void set_signals();
  155. struct descriptor_data *new_connection();
  156. void parse_connect();
  157. void set_userstring();
  158. int do_command();
  159. char *strsave();
  160. int make_socket();
  161. int queue_string();
  162. int queue_write();
  163. int process_output();
  164. int process_input();
  165. int bailout();
  166. void srand();
  167. void announce_connect();
  168. void announce_disconnect();
  169. const char *time_format_1();
  170. const char *time_format_2();
  171.  
  172. #ifdef IDLE_TIMEOUT
  173. void inactivity_check();
  174. #endif
  175.  
  176. #ifndef BOOLEXP_DEBUGGING
  177. void main(argc, argv)
  178.     int argc;
  179.     char **argv;
  180. {
  181. #ifdef AUTORESTART
  182.   FILE *id;
  183. #endif
  184.  
  185.   /* read the configuration file */
  186.   if (argc < 1) {
  187.     fprintf(stderr, "ERROR: No configuration file! Exiting.\n");
  188.     exit(2);
  189.   }
  190.  
  191. #ifndef SINGLE_LOGFILE
  192.   /* open the log files */
  193.   start_log(&connlog_fp, CONNLOG);
  194.   start_log(&checklog_fp, CHECKLOG);
  195.   start_log(&wizlog_fp, WIZLOG);
  196.   start_log(&tracelog_fp, TRACELOG);
  197.   start_log(&cmdlog_fp, CMDLOG);
  198. #else
  199.   connlog_fp = checklog_fp = wizlog_fp = tracelog_fp = cmdlog_fp = stderr;
  200. #endif                /* SINGLE_LOGFILE */
  201.  
  202. /*  this writes a file used by the restart script to check for active mush */
  203. #ifdef AUTORESTART
  204.   id = fopen("runid", "w");
  205.   fprintf(id, "%d", getpid());
  206.   fclose(id);
  207. #endif
  208.  
  209.   srand(time(NULL));
  210.   
  211.   /* save a file descriptor */
  212.   reserved = open("/dev/null", O_RDWR);
  213.  
  214.   if (init_game(argv[1]) < 0) {
  215.     fprintf(stderr, "ERROR: Couldn't load %s! Exiting.\n", DEF_DB_IN);
  216.     exit(2);
  217.   }
  218.   set_signals();
  219. #ifdef RWHO_SEND
  220.   rwhocli_setup(RWHOSERV, RWHOPASS, MUDNAME, SHORTVN);
  221. #endif
  222.  
  223.   /* go do it */
  224.   shovechars(TINYPORT);
  225.  
  226.   /* someone has told us to shut down */
  227.  
  228. #ifdef ALLOW_RPAGE
  229.   rpage_shutdown();        /* do this first */
  230. #endif                /* ALLOW_RPAGE */
  231.  
  232.   close_sockets();
  233.   dump_database();
  234.  
  235. #ifndef SINGLE_LOGFILE
  236.   /* close up the log files */
  237.   end_log(connlog_fp);
  238.   end_log(checklog_fp);
  239.   end_log(wizlog_fp);
  240.   end_log(tracelog_fp);
  241.   end_log(cmdlog_fp);
  242. #endif                /* SINGLE_LOGFILE */
  243.  
  244. #ifdef HAS_RUSAGE
  245.   rusage_stats();
  246. #endif                /* HAS_RUSAGE */
  247.  
  248.   fprintf(stderr, "\nMUSH shutdown completed.\n");
  249.   fflush(stderr);
  250.  
  251.   close(sock);            /* patch moving this line here fixes
  252.                  * @shutdown error */
  253.  
  254.   exit(0);
  255. }
  256. #endif                /* BOOLEXP_DEBUGGING */
  257.  
  258. void set_signals()
  259. {
  260.   /* we don't care about SIGPIPE, we notice it in select() and write() */
  261.   signal(SIGPIPE, SIG_IGN);
  262.  
  263.   /* standard termination signals */
  264.   signal(SIGINT, (void *)bailout);
  265.   signal(SIGTERM, (void *)bailout);
  266. }
  267.  
  268. void raw_notify(player, msg)
  269.     dbref player;
  270.     const char *msg;
  271. {
  272.   struct descriptor_data *d;
  273.   if (!msg || *msg == '\0')
  274.     return;
  275.   if (!Connected(player) && options.login_allow && under_limit)
  276.     return;
  277.   for (d = descriptor_list; d; d = d->next) {
  278.     if (d->connected && d->player == player) {
  279.       queue_string(d, msg);
  280.       queue_write(d, "\n", 1);
  281.     }
  282.   }
  283. }
  284.  
  285. void raw_broadcast(inflags, va_alist)
  286.      object_flag_type inflags;
  287.      va_dcl
  288. {
  289.   /* takes a flag mask, format string, and format args, and notifies
  290.    * all connected players with that flag mask of something. Players
  291.    * with _at least_ one of the bits in the flag mask are notified,
  292.    * rather than players with that _entire_ flag mask. The former
  293.    * behavior is more useful.
  294.    */
  295.  
  296.   va_list args;
  297.   char *fmt;
  298.   char tbuf1[BUFFER_LEN];
  299.   DESC *d;
  300.  
  301.   va_start(args);
  302.   fmt = va_arg(args, char *);
  303.  
  304.   (void) vsprintf(tbuf1, fmt, args);
  305.  
  306.   DESC_ITER_CONN(d) {
  307.     if ((Flags(d->player) & inflags) || !inflags) {
  308.       queue_string(d, tbuf1);
  309.       queue_write(d, "\n", 1);
  310.       process_output(d);
  311.     }
  312.   }
  313. }
  314.  
  315. static void toggle_broadcast(inflags, va_alist)
  316.      object_flag_type inflags;
  317.      va_dcl
  318. {
  319.   /* like raw_broadcast but uses toggles.
  320.    */
  321.  
  322.   va_list args;
  323.   char *fmt;
  324.   char tbuf1[BUFFER_LEN];
  325.   DESC *d;
  326.  
  327.   va_start(args);
  328.   fmt = va_arg(args, char *);
  329.  
  330.   (void) vsprintf(tbuf1, fmt, args);
  331.  
  332.   DESC_ITER_CONN(d) {
  333.     if ((Toggles(d->player) & inflags) || !inflags) {
  334.       queue_string(d, tbuf1);
  335.       queue_write(d, "\n", 1);
  336.       process_output(d);
  337.     }
  338.   }
  339. }
  340.  
  341. struct timeval timeval_sub(now, then)
  342.     struct timeval now;
  343.     struct timeval then;
  344. {
  345.   now.tv_sec -= then.tv_sec;
  346.   now.tv_usec -= then.tv_usec;
  347.   if (now.tv_usec < 0) {
  348.     now.tv_usec += 1000000;
  349.     now.tv_sec--;
  350.   }
  351.   return now;
  352. }
  353.  
  354. long msec_diff(now, then)
  355.     struct timeval now;
  356.     struct timeval then;
  357. {
  358.   return ((now.tv_sec - then.tv_sec) * 1000
  359.       + (now.tv_usec - then.tv_usec) / 1000);
  360. }
  361.  
  362. struct timeval msec_add(t, x)
  363.     struct timeval t;
  364.     int x;
  365. {
  366.   t.tv_sec += x / 1000;
  367.   t.tv_usec += (x % 1000) * 1000;
  368.   if (t.tv_usec >= 1000000) {
  369.     t.tv_sec += t.tv_usec / 1000000;
  370.     t.tv_usec = t.tv_usec % 1000000;
  371.   }
  372.   return t;
  373. }
  374.  
  375. struct timeval update_quotas(last, current)
  376.     struct timeval last;
  377.     struct timeval current;
  378. {
  379.   int nslices;
  380.   struct descriptor_data *d;
  381.   nslices = (int) msec_diff(current, last) / COMMAND_TIME_MSEC;
  382.  
  383.   if (nslices > 0) {
  384.     for (d = descriptor_list; d; d = d->next) {
  385.       d->quota += COMMANDS_PER_TIME * nslices;
  386.       if (d->quota > COMMAND_BURST_SIZE)
  387.     d->quota = COMMAND_BURST_SIZE;
  388.     }
  389.   }
  390.   return msec_add(last, nslices * COMMAND_TIME_MSEC);
  391. }
  392.  
  393. void shovechars(port)
  394.     int port;
  395. {
  396.   /* this is the main game loop */
  397.  
  398.   fd_set input_set, output_set;
  399.   time_t now;
  400.   struct timeval last_slice, current_time;
  401.   struct timeval next_slice;
  402.   struct timeval timeout, slice_timeout;
  403.   int maxd, found;
  404.   struct descriptor_data *d, *dnext;
  405.   struct descriptor_data *newd;
  406.   int avail_descriptors;
  407.   extern void dispatch();
  408.  
  409.   sock = make_socket(port);
  410.   maxd = sock + 1;
  411.   gettimeofday(&last_slice, (struct timezone *) 0);
  412.  
  413. #ifdef HPUX
  414.   avail_descriptors = sysconf(_SC_OPEN_MAX);
  415. #else
  416.   avail_descriptors = getdtablesize() - 4;
  417. #endif
  418.  
  419.   /* done. print message to the log */
  420.   fprintf(stderr, "RESTART FINISHED.\n");
  421.   fflush(stderr);
  422.  
  423.   while (shutdown_flag == 0) {
  424.     gettimeofday(¤t_time, (struct timezone *) 0);
  425.     last_slice = update_quotas(last_slice, current_time);
  426.  
  427.     process_commands();
  428.  
  429.     if (shutdown_flag)
  430.       break;
  431.  
  432.     /* test for events */
  433.     dispatch();
  434.  
  435. #ifdef ALLOW_RPAGE
  436.     /* anything received on our datagram remote page? */
  437.     recv_rpage();
  438. #endif                /* ALLOW_RPAGE */
  439.  
  440.     /* any queued robot commands waiting? */
  441.     timeout.tv_sec = test_top() ? 0 : 1000;
  442.     timeout.tv_usec = 0;
  443.     next_slice = msec_add(last_slice, COMMAND_TIME_MSEC);
  444.     slice_timeout = timeval_sub(next_slice, current_time);
  445.  
  446.     FD_ZERO(&input_set);
  447.     FD_ZERO(&output_set);
  448.     if (ndescriptors < avail_descriptors)
  449.       FD_SET(sock, &input_set);
  450.     for (d = descriptor_list; d; d = d->next) {
  451.       if (d->input.head)
  452.     timeout = slice_timeout;
  453.       else
  454.     FD_SET(d->descriptor, &input_set);
  455.       if (d->output.head)
  456.     FD_SET(d->descriptor, &output_set);
  457.     }
  458.  
  459.     if ((found = select(maxd, &input_set, &output_set,
  460.             (fd_set *) 0, &timeout)) < 0) {
  461.       if (errno != EINTR) {
  462.     perror("select");
  463.     return;
  464.       }
  465.     } else {
  466.       /* if !found then time for robot commands */
  467.       if (!found) {
  468.     do_top();
  469.     do_top();
  470.     do_top();
  471.     continue;
  472.       }
  473.       now = time((time_t *) 0);
  474.       if (FD_ISSET(sock, &input_set)) {
  475.     if (!(newd = new_connection(sock))) {
  476.       if (errno
  477.           && errno != EINTR
  478.           && errno != EMFILE
  479.           && errno != ENFILE) {
  480.         perror("new_connection");
  481.         return;
  482.       }
  483.     } else {
  484.       if (newd->descriptor >= maxd)
  485.         maxd = newd->descriptor + 1;
  486.     }
  487.       }
  488.       for (d = descriptor_list; d; d = dnext) {
  489.     dnext = d->next;
  490.     if (FD_ISSET(d->descriptor, &input_set)) {
  491.       d->last_time = now;
  492.       if (!process_input(d)) {
  493.         shutdownsock(d);
  494.         continue;
  495.       }
  496.     }
  497.     if (FD_ISSET(d->descriptor, &output_set)) {
  498.       if (!process_output(d)) {
  499.         shutdownsock(d);
  500.       }
  501.     }
  502.       }
  503.     }
  504.   }
  505. }
  506.  
  507. struct descriptor_data *new_connection(oldsock)
  508.     int oldsock;
  509. {
  510.   int newsock;
  511.   struct sockaddr_in addr;
  512.   int addr_len;
  513.   char tbuf1[BUFFER_LEN];
  514.  
  515.   addr_len = sizeof(addr);
  516.   newsock = accept(oldsock, (struct sockaddr *) &addr, &addr_len);
  517.   if (newsock < 0) {
  518.     return 0;
  519. #ifdef LOCKOUT
  520.   } else if (forbidden_site(1, hostname_convert(addr.sin_addr))) {
  521.       do_log(LT_CONN, 0, 0, "[%d/%s] Refused connection (remote port %d)",
  522.          newsock, hostname_convert(addr.sin_addr), ntohs(addr.sin_port));
  523.       shutdown(newsock, 2);
  524.       close(newsock);
  525.       errno = 0;
  526.       return 0;
  527. #endif                /* LOCKOUT */
  528.   } else {
  529.     strcpy(tbuf1, (char *)hostname_convert(addr.sin_addr));
  530.     do_log(LT_CONN, 0, 0, "[%d/%s] Connection opened.", newsock, tbuf1);
  531.     return initializesock(newsock, &addr, tbuf1);
  532.   }
  533. }
  534.  
  535. void clearstrings(d)
  536.     struct descriptor_data *d;
  537. {
  538.   if (d->output_prefix) {
  539.     free((void *) d->output_prefix);
  540. #ifdef MEM_CHECK
  541.     del_check("userstring");
  542. #endif
  543.     d->output_prefix = 0;
  544.   }
  545.   if (d->output_suffix) {
  546.     free((void *)d->output_suffix);
  547. #ifdef MEM_CHECK
  548.     del_check("userstring");
  549. #endif
  550.     d->output_suffix = 0;
  551.   }
  552. }
  553.  
  554. void fcache_dump(d, fp)
  555.      DESC *d;
  556.      FBLOCK *fp;
  557. {
  558.   while (fp != NULL) {
  559.     queue_write(d, fp->data, fp->hdr.nchars);
  560.     fp = fp->hdr.nxt;
  561.   }
  562. }
  563.  
  564. int fcache_read(cp, filename)
  565.      FBLOCK **cp;
  566.      char *filename;
  567. {
  568.   int n, nmax, fd, tchars;
  569.   char *bufp;
  570.   FBLOCK *fp, *tfp;
  571.  
  572.   /* Free prior buffer chain */
  573.   fp = *cp;
  574.   while (fp != NULL) {
  575.     tfp = fp->hdr.nxt;
  576.     free(fp);
  577.     fp = tfp;
  578.   }
  579.   *cp = NULL;
  580.  
  581.   /* Read the text file into a new chain */
  582.   close(reserved);
  583.   if ((fd = open(filename, O_RDONLY, 0)) == -1) {
  584.       do_log(LT_ERR, 0, 0, "couldn't open cached text file '%s'", filename);
  585.       return -1;
  586.   }
  587.   fp = (FBLOCK *)malloc(sizeof(char) * 256);
  588.   fp->hdr.nxt = NULL;
  589.   fp->hdr.nchars = 0;
  590.   *cp = fp;
  591.   tfp = NULL;
  592.   tchars = 0;
  593.  
  594.   /* Read in the first chunk of the file */
  595.   nmax = FBLOCK_SIZE;
  596.   bufp = fp->data;
  597.   n = read(fd, bufp, nmax);
  598.   while (n > 0) {
  599.     /* if we didn't read in all we wanted, update the pointers and try to
  600.      * fill the current buffer.
  601.      */
  602.     fp->hdr.nchars += n;
  603.     tchars += n;
  604.     if (fp->hdr.nchars < FBLOCK_SIZE) {
  605.       nmax -= n;
  606.       bufp += n;
  607.     } else {
  608.       /* filled the current buffer. Get a new one. */
  609.       tfp = fp;
  610.       fp = (FBLOCK *)malloc(sizeof(char) * 256);
  611.       fp->hdr.nxt = NULL;
  612.       fp->hdr.nchars = 0;
  613.       tfp->hdr.nxt = fp;
  614.       nmax = FBLOCK_SIZE;
  615.       bufp = fp->data;
  616.     }
  617.     /* read in the next chunk of the file */
  618.     n = read(fd, bufp, nmax);
  619.   }
  620.   close(fd);
  621.   reserved = open("/dev/null", O_RDWR);
  622.   if (fp->hdr.nchars == 0) {
  623.     free(fp);
  624.     if (tfp == NULL)
  625.       *cp = NULL;
  626.     else
  627.       tfp->hdr.nxt = NULL;
  628.   }
  629.   return tchars;
  630. }
  631.  
  632. void fcache_load(player)
  633.      dbref player;
  634. {
  635.     int conn, motd, wiz, new, reg, quit, down, full;
  636.  
  637.     conn = fcache_read(&options.connect_fcache, options.connect_file);
  638.     motd = fcache_read(&options.motd_fcache, options.motd_file);
  639.     wiz = fcache_read(&options.wizmotd_fcache, options.wizmotd_file);
  640.     new = fcache_read(&options.newuser_fcache, options.newuser_file);
  641.     reg = fcache_read(&options.register_fcache, options.register_file);
  642.     quit = fcache_read(&options.quit_fcache, options.quit_file);
  643.     down = fcache_read(&options.down_fcache, options.down_file);
  644.     full = fcache_read(&options.full_fcache, options.full_file);
  645.  
  646.     if (player != NOTHING) {
  647.     notify(player, 
  648.            tprintf("File sizes:  NewUser...%d  Connect...%d  Motd...%d  Wizmotd...%d  Quit...%d  Register...%d  Down...%d  Full...%d",
  649.                new, conn, motd, wiz, quit, reg, down, full));
  650.     }
  651. }
  652.  
  653. void fcache_init()
  654. {
  655.     options.connect_fcache = NULL;
  656.     options.motd_fcache = NULL;
  657.     options.wizmotd_fcache = NULL;
  658.     options.newuser_fcache = NULL;
  659.     options.register_fcache = NULL;
  660.     options.quit_fcache = NULL;
  661.     options.down_fcache = NULL;
  662.     options.full_fcache = NULL;
  663.   fcache_load(NOTHING);
  664. }
  665.  
  666. void logout_sock(d)
  667.      struct descriptor_data *d;
  668. {
  669.   if (d->connected) {
  670.     fcache_dump(d, options.quit_fcache);
  671.     do_log(LT_CONN, 0, 0, "[%d/%s] Logout by %s(#%d) <Connection not dropped>",
  672.        d->descriptor, d->addr, Name(d->player), d->player);
  673.     fflush(connlog_fp);
  674.     announce_disconnect(d->player);
  675. #ifdef LOGIN_LIMIT
  676.     login_number--;
  677.     if (!under_limit && (login_number < MAX_LOGINS)) {
  678.     under_limit = 1;
  679.     do_log(LT_CONN, 0, 0,
  680.            "Below maximum player limit of %d. Logins enabled.",
  681.            MAX_LOGINS);
  682.     }
  683. #endif                /* LOGIN_LIMIT */
  684.   } else {
  685.     do_log(LT_CONN, 0, 0,
  686.        "[%d/%s] Logout, never connected. <Connection not dropped>",
  687.        d->descriptor, d->addr);
  688.   }
  689.   process_output(d);        /* flush our old output */
  690.   /* pretend we have a new connection */
  691.   d->connected = 0;
  692.   d->output_prefix = 0;
  693.   d->output_suffix = 0;
  694.   d->output_size = 0;
  695.   d->output.head = 0;
  696.   d->player = 0;
  697.   d->output.tail = &d->output.head;
  698.   d->input.head = 0;
  699.   d->input.tail = &d->input.head;
  700.   d->raw_input = 0;
  701.   d->raw_input_at = 0;
  702.   d->quota = COMMAND_BURST_SIZE;
  703.   d->last_time = 0;
  704.   d->cmds = 0;
  705.   d->hide = 0;
  706. #ifdef AT_DOING
  707.   d->doing[0] = '\0';
  708. #endif                /* AT_DOING */
  709.   welcome_user(d);
  710. }
  711.  
  712. void shutdownsock(d)
  713.     struct descriptor_data *d;
  714. {
  715.   if (d->connected) {
  716.     fcache_dump(d, options.quit_fcache);
  717.     do_log(LT_CONN, 0, 0, "[%d/%s] Logout by %s(#%d)",
  718.        d->descriptor, d->addr, Name(d->player), d->player);
  719.     fflush(connlog_fp);
  720.     announce_disconnect(d->player);
  721. #ifdef LOGIN_LIMIT
  722.     login_number--;
  723.     if (!under_limit && (login_number < MAX_LOGINS)) {
  724.     under_limit = 1;
  725.     do_log(LT_CONN, 0, 0,
  726.            "Below maximum player limit of %d. Logins enabled.",
  727.            MAX_LOGINS);
  728.     }
  729. #endif                /* LOGIN_LIMIT */
  730.   } else {
  731.       do_log(LT_CONN, 0, 0, "[%d/%s] Connection closed, never connected.",
  732.          d->descriptor, d->addr);
  733.   }
  734.   process_output(d);
  735.   clearstrings(d);
  736.   shutdown(d->descriptor, 2);
  737.   close(d->descriptor);
  738.   freeqs(d);
  739.   *d->prev = d->next;
  740.   if (d->next)
  741.     d->next->prev = d->prev;
  742.   free((void *) d);
  743. #ifdef MEM_CHECK
  744.   del_check("descriptor");
  745. #endif
  746.   ndescriptors--;
  747. }
  748.  
  749. struct descriptor_data *initializesock(s, a, addr)
  750.     int s;
  751.     struct sockaddr_in *a;
  752.     char *addr;
  753. {
  754.   struct descriptor_data *d;
  755.   ndescriptors++;
  756.   d = (struct descriptor_data *) malloc(sizeof(struct descriptor_data));
  757.   if(!d)
  758.     panic("Out of memory.");
  759. #ifdef MEM_CHECK
  760.   add_check("descriptor");
  761. #endif
  762.   d->descriptor = s;
  763.   d->connected = 0;
  764.   make_nonblocking(s);
  765.   d->output_prefix = 0;
  766.   d->output_suffix = 0;
  767.   d->output_size = 0;
  768.   d->output.head = 0;
  769.   d->player = 0;
  770.   d->output.tail = &d->output.head;
  771.   d->input.head = 0;
  772.   d->input.tail = &d->input.head;
  773.   d->raw_input = 0;
  774.   d->raw_input_at = 0;
  775.   d->quota = COMMAND_BURST_SIZE;
  776.   d->last_time = 0;
  777.   d->cmds = 0;
  778.   d->hide = 0;
  779. #ifdef AT_DOING
  780.   d->doing[0] = '\0';
  781. #endif
  782.   strncpy(d->addr, addr, 50);
  783.   d->address = *a;        /* added 5/3/90 SCG */
  784.   if (descriptor_list)
  785.     descriptor_list->prev = &d->next;
  786.   d->next = descriptor_list;
  787.   d->prev = &descriptor_list;
  788.   descriptor_list = d;
  789.   welcome_user(d);
  790.   return d;
  791. }
  792.  
  793. int make_socket(port)
  794.     int port;
  795. {
  796.   int s;
  797.   struct sockaddr_in server;
  798.   int opt;
  799.   s = socket(AF_INET, SOCK_STREAM, 0);
  800.   if (s < 0) {
  801.     perror("creating stream socket");
  802.     exit(3);
  803.   }
  804.   opt = 1;
  805.   if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR,
  806.          (char *) &opt, sizeof(opt)) < 0) {
  807.     perror("setsockopt");
  808.     exit(1);
  809.   }
  810.   server.sin_family = AF_INET;
  811.   server.sin_addr.s_addr = INADDR_ANY;
  812.   server.sin_port = htons(port);
  813.   if (bind(s, (struct sockaddr *) & server, sizeof(server))) {
  814.     perror("binding stream socket");
  815.     close(s);
  816.     exit(4);
  817.   }
  818.   listen(s, 5);
  819.   return s;
  820. }
  821.  
  822. struct text_block *make_text_block(s, n)
  823.     const char *s;
  824.     int n;
  825. {
  826.   struct text_block *p;
  827.   p = (struct text_block *) malloc(sizeof(struct text_block));
  828.   if(!p)
  829.     panic("Out of memory");
  830.   p->buf = (char *) malloc(sizeof(char) * n);
  831.   if(!p->buf)
  832.     panic("Out of memory");
  833.  
  834. #ifdef MEM_CHECK
  835.   add_check("text_block");
  836.   add_check("text_block_buff");
  837. #endif
  838.   bcopy(s, p->buf, n);
  839.   p->nchars = n;
  840.   p->start = p->buf;
  841.   p->nxt = 0;
  842.   return p;
  843. }
  844.  
  845. void free_text_block(t)
  846.     struct text_block *t;
  847. {
  848.    if (t) {
  849.     if (t->buf)    
  850.         free((void *) t->buf);
  851.     free((void *) t);
  852.     }
  853. #ifdef MEM_CHECK
  854.   del_check("text_block");
  855.   del_check("text_block_buff");
  856. #endif
  857. }
  858.  
  859. void add_to_queue(q, b, n)
  860.     struct text_queue *q;
  861.     const char *b;
  862.     int n;
  863. {
  864.   struct text_block *p;
  865.   if (n == 0)
  866.     return;
  867.  
  868.   p = make_text_block(b, n);
  869.   p->nxt = 0;
  870.   *q->tail = p;
  871.   q->tail = &p->nxt;
  872. }
  873.  
  874. int flush_queue(q, n)
  875.     struct text_queue *q;
  876.     int n;
  877. {
  878.   struct text_block *p;
  879.   int really_flushed = 0;
  880.   n += strlen(flushed_message);
  881.  
  882.   while (n > 0 && (p = q->head)) {
  883.     n -= p->nchars;
  884.     really_flushed += p->nchars;
  885.     q->head = p->nxt;
  886. #ifdef DEBUG
  887.     fprintf(stderr, "free_text_block(0x%x) at 1.\n", p);
  888. #endif /* DEBUG */
  889.     free_text_block(p);
  890.   }
  891.   p = make_text_block(flushed_message, strlen(flushed_message));
  892.   p->nxt = q->head;
  893.   q->head = p;
  894.   if (!p->nxt)
  895.     q->tail = &p->nxt;
  896.   really_flushed -= p->nchars;
  897.   return really_flushed;
  898. }
  899.  
  900. int queue_write(d, b, n)
  901.     struct descriptor_data *d;
  902.     const char *b;
  903.     int n;
  904. {
  905.   int space;
  906.   space = MAX_OUTPUT - d->output_size - n;
  907.   if (space < 0)
  908.     d->output_size -= flush_queue(&d->output, -space);
  909.   add_to_queue(&d->output, b, n);
  910.   d->output_size += n;
  911.   return n;
  912. }
  913.  
  914. int queue_string(d, s)
  915.     struct descriptor_data *d;
  916.     const char *s;
  917. {
  918.   return queue_write(d, s, strlen(s));
  919. }
  920.  
  921. int process_output(d)
  922.     struct descriptor_data *d;
  923. {
  924.   struct text_block **qp, *cur;
  925.   int cnt;
  926.   for (qp = &d->output.head; ((cur = *qp) != NULL); ) {
  927.     cnt = write(d->descriptor, cur->start, cur->nchars);
  928.     if (cnt < 0) {
  929.       if (errno == EWOULDBLOCK)
  930.     return 1;
  931.       return 0;
  932.     }
  933.     d->output_size -= cnt;
  934.     if (cnt == cur->nchars) {
  935.       if (!cur->nxt)
  936.     d->output.tail = qp;
  937.       *qp = cur->nxt;
  938. #ifdef DEBUG
  939.       fprintf(stderr, "free_text_block(0x%x) at 2.\n", cur);
  940. #endif /* DEBUG */
  941.       free_text_block(cur);
  942.       continue;            /* do not adv ptr */
  943.     }
  944.     cur->nchars -= cnt;
  945.     cur->start += cnt;
  946.     break;
  947.   }
  948.   return 1;
  949. }
  950.  
  951. void make_nonblocking(s)
  952.     int s;
  953. {
  954.   if (fcntl(s, F_SETFL, O_NDELAY) == -1) {
  955.     perror("make_nonblocking: fcntl");
  956.     panic("O_NDELAY fcntl failed");
  957.   }
  958. }
  959.  
  960. void freeqs(d)
  961.     struct descriptor_data *d;
  962. {
  963.   struct text_block *cur, *next;
  964.   cur = d->output.head;
  965.   while (cur) {
  966.     next = cur->nxt;
  967. #ifdef DEBUG
  968.     fprintf(stderr, "free_text_block(0x%x) at 3.\n", cur);
  969. #endif /* DEBUG */
  970.     free_text_block(cur);
  971.     cur = next;
  972.   }
  973.   d->output.head = 0;
  974.   d->output.tail = &d->output.head;
  975.  
  976.   cur = d->input.head;
  977.   while (cur) {
  978.     next = cur->nxt;
  979. #ifdef DEBUG
  980.     fprintf(stderr, "free_text_block(0x%x) at 4.\n", cur);
  981. #endif /* DEBUG */
  982.     free_text_block(cur);
  983.     cur = next;
  984.   }
  985.   d->input.head = 0;
  986.   d->input.tail = &d->input.head;
  987.  
  988.   if (d->raw_input) {
  989.     free((void *) d->raw_input);
  990. #ifdef MEM_CHECK
  991.     del_check("descriptor_raw_input");
  992. #endif
  993.   }
  994.   d->raw_input = 0;
  995.   d->raw_input_at = 0;
  996. }
  997.  
  998. void welcome_user(d)
  999.     struct descriptor_data *d;
  1000. {
  1001.   fcache_dump(d, options.connect_fcache);
  1002. }
  1003.  
  1004. #ifdef NEVER
  1005. void spew_message(d, filename)
  1006.     struct descriptor_data *d;
  1007.     char *filename;
  1008. {
  1009.   int n, fd;
  1010.   char buf[512];
  1011.   close(reserved);
  1012.   if ((fd = open(filename, O_RDONLY)) != -1) {
  1013.     while ((n = read(fd, buf, 512)) > 0)
  1014.       queue_write(d, buf, n);
  1015.     close(fd);
  1016.     queue_write(d, "\n", 1);
  1017.   }
  1018.   reserved = open("/dev/null", O_RDWR);
  1019. }
  1020. #endif
  1021.  
  1022. void do_new_spitfile(player, arg1, index_file, text_file)
  1023.     dbref player;
  1024.     char *arg1;
  1025.     char *index_file;
  1026.     char *text_file;
  1027. {
  1028.   int help_found;
  1029.   help_indx entry;
  1030.   FILE *fp;
  1031.   char *p, line[LINE_SIZE + 1];
  1032.   if (*arg1 == '\0')
  1033.     arg1 = (char *) "help";
  1034.  
  1035.   if ((fp = fopen(index_file, "r")) == NULL) {
  1036.     notify(player, "Sorry, that function is temporarily unavailable.");
  1037.     do_log(LT_ERR, 0, 0, "Can't open index file %s for reading", index_file);
  1038.     return;
  1039.   }
  1040.   while ((help_found = fread(&entry, sizeof(help_indx), 1, fp)) == 1)
  1041.     if (string_prefix(entry.topic, arg1))
  1042.       break;
  1043.   fclose(fp);
  1044.   if (!help_found) {
  1045.     notify(player, tprintf("No entry for '%s'.", arg1));
  1046.     return;
  1047.   }
  1048.   if ((fp = fopen(text_file, "r")) == NULL) {
  1049.     notify(player, "Sorry, that function is temporarily unavailable.");
  1050.     do_log(LT_ERR, 0, 0, "Can't open text file %s for reading", text_file);
  1051.     return;
  1052.   }
  1053.   if (fseek(fp, entry.pos, 0) < 0L) {
  1054.     notify(player, "Sorry, that function is temporarily unavailable.");
  1055.     do_log(LT_ERR, 0, 0, "Seek error in file %s\n", text_file);
  1056.     return;
  1057.   }
  1058.   for (;;) {
  1059.     if (fgets(line, LINE_SIZE, fp) == NULL)
  1060.       break;
  1061.     if (line[0] == '&')
  1062.       break;
  1063.     for (p = line; *p != '\0'; p++)
  1064.       if (*p == '\n')
  1065.     *p = '\0';
  1066.     notify(player, line);
  1067.   }
  1068.   fclose(fp);
  1069. }
  1070.  
  1071.  
  1072. char *strsave(s)
  1073.     const char *s;
  1074. {
  1075.   char *p;
  1076.   p = (char *) malloc(sizeof(char) * (strlen(s)+1));
  1077.   if(!p)
  1078.     panic("Out of memory");
  1079.  
  1080. #ifdef MEM_CHECK
  1081.   add_check("userstring");
  1082. #endif
  1083.   if (p)
  1084.     strcpy(p, s);
  1085.   return p;
  1086. }
  1087.  
  1088. void save_command(d, command)
  1089.     struct descriptor_data *d;
  1090.     const char *command;
  1091. {
  1092.   add_to_queue(&d->input, command, strlen(command) + 1);
  1093. }
  1094.  
  1095. int process_input(d)
  1096.     struct descriptor_data *d;
  1097. {
  1098.   int got;
  1099.   char *p, *pend, *q, *qend;
  1100.   char tbuf1[BUFFER_LEN];
  1101.  
  1102.   got = read(d->descriptor, tbuf1, sizeof tbuf1);
  1103.   if (got <= 0)
  1104.     return 0;
  1105.   if (!d->raw_input) {
  1106.     d->raw_input = (char *) malloc(sizeof(char) * MAX_COMMAND_LEN);
  1107.     if(!d->raw_input)
  1108.       panic("Out of memory");
  1109. #ifdef MEM_CHECK
  1110.     add_check("descriptor_raw_input");
  1111. #endif
  1112.     d->raw_input_at = d->raw_input;
  1113.   }
  1114.   p = d->raw_input_at;
  1115.   pend = d->raw_input + MAX_COMMAND_LEN - 1;
  1116.   for (q = tbuf1, qend = tbuf1 + got; q < qend; q++) {
  1117.     if (*q == '\n') {
  1118.       *p = '\0';
  1119.       if (p > d->raw_input)
  1120.     save_command(d, d->raw_input);
  1121.       p = d->raw_input;
  1122.     } else if (p < pend && isascii(*q) && isprint(*q)) {
  1123.       *p++ = *q;
  1124.     }
  1125.   }
  1126.   if (p > d->raw_input) {
  1127.     d->raw_input_at = p;
  1128.   } else {
  1129.     free((void *) d->raw_input);
  1130. #ifdef MEM_CHECK
  1131.     del_check("descriptor_raw_input");
  1132. #endif
  1133.     d->raw_input = 0;
  1134.     d->raw_input_at = 0;
  1135.   }
  1136.   return 1;
  1137. }
  1138.  
  1139. void set_userstring(userstring, command)
  1140.     char **userstring;
  1141.     const char *command;
  1142. {
  1143.   if (*userstring) {
  1144.     free((void *) *userstring);
  1145. #ifdef MEM_CHECK
  1146.     del_check("userstring");
  1147. #endif
  1148.     *userstring = 0;
  1149.   }
  1150.   while (*command && isascii(*command) && isspace(*command))
  1151.     command++;
  1152.   if (*command)
  1153.     *userstring = strsave(command);
  1154. }
  1155.  
  1156. void process_commands()
  1157. {
  1158.   int nprocessed;
  1159.   struct descriptor_data *d, *dnext;
  1160.   struct text_block *t;
  1161.   int retval;
  1162.  
  1163.   do {
  1164.     nprocessed = 0;
  1165.     for (d = descriptor_list; d; d = dnext) {
  1166.       dnext = d->next;
  1167.       if (d->quota > 0 && (t = d->input.head)) {
  1168.     d->quota--;
  1169.     nprocessed++;
  1170.     retval = do_command(d, t->start);
  1171.     if (retval == 0) {
  1172.       shutdownsock(d);
  1173.     } else if (retval == -1) {
  1174.       logout_sock(d);
  1175.     } else {
  1176.       d->input.head = t->nxt;
  1177.       if (!d->input.head)
  1178.         d->input.tail = &d->input.head;
  1179.       if (t) {
  1180. #ifdef DEBUG
  1181.         fprintf(stderr, "free_text_block(0x%x) at 5.\n", t);
  1182. #endif /* DEBUG */
  1183.         free_text_block(t);
  1184.       }
  1185.     }
  1186.       }
  1187.     }
  1188.   } while (nprocessed > 0);
  1189. }
  1190.  
  1191. int do_command(d, command)
  1192.     struct descriptor_data *d;
  1193.     char *command;
  1194. {
  1195.   depth = 0;
  1196.   (d->cmds)++;
  1197.  
  1198.   if (!strcmp(command, QUIT_COMMAND)) {
  1199.     return 0;
  1200.   } else if (!strcmp(command, LOGOUT_COMMAND)) {
  1201.     return -1;
  1202.   } else if (!strncmp(command, WHO_COMMAND, strlen(WHO_COMMAND))) {
  1203.     if (d->output_prefix) {
  1204.       queue_string(d, d->output_prefix);
  1205.       queue_write(d, "\n", 1);
  1206.     }
  1207.     dump_users(d,command+strlen(WHO_COMMAND),0);
  1208.     if (d->output_suffix) {
  1209.       queue_string(d, d->output_suffix);
  1210.       queue_write(d, "\n", 1);
  1211.     }
  1212. #ifdef AT_DOING
  1213.   } else if (!strncmp(command, DOING_COMMAND, strlen(DOING_COMMAND))) {
  1214.     if (d->output_prefix) {
  1215.       queue_string(d, d->output_prefix);
  1216.       queue_write(d, "\n", 1);
  1217.     }
  1218.     dump_users(d,command+strlen(DOING_COMMAND),1);
  1219.     if (d->output_suffix) {
  1220.       queue_string(d, d->output_suffix);
  1221.       queue_write(d, "\n", 1);
  1222.     }
  1223. #endif
  1224.   } else if (!strncmp(command, PREFIX_COMMAND, strlen(PREFIX_COMMAND))) {
  1225.     set_userstring(&d->output_prefix, command + strlen(PREFIX_COMMAND));
  1226.   } else if (!strncmp(command, SUFFIX_COMMAND, strlen(SUFFIX_COMMAND))) {
  1227.     set_userstring(&d->output_suffix, command + strlen(SUFFIX_COMMAND));
  1228. #ifdef RWHO_SEND
  1229. #ifdef FULL_RWHO
  1230.   } else if (!strcmp(command, RWHO_COMMAND)) {
  1231.     dump_rusers(d);
  1232. #endif
  1233. #endif
  1234.   } else {
  1235.     if (d->connected) {
  1236.       if (d->output_prefix) {
  1237.     queue_string(d, d->output_prefix);
  1238.     queue_write(d, "\n", 1);
  1239.       }
  1240.       cplr = d->player;
  1241.       strcpy(ccom, command);
  1242.       process_command(d->player, command, d->player, 1);
  1243.       if (d->output_suffix) {
  1244.     queue_string(d, d->output_suffix);
  1245.     queue_write(d, "\n", 1);
  1246.       }
  1247.     } else {
  1248.       if (!check_connect(d, command))
  1249.           return 0;
  1250.     }
  1251.   }
  1252.   return 1;
  1253. }
  1254.  
  1255. static int dump_messages(d, player, new)
  1256.      DESC *d;
  1257.      dbref player;
  1258.      int new;            /* 0 if connect, 1 if create */
  1259. {
  1260.     d->connected = 1;
  1261.     d->connected_at = time((time_t *) 0);
  1262.     d->player = player;
  1263. #ifdef AT_DOING
  1264.     d->doing[0] = '\0';
  1265. #endif
  1266.  
  1267. #ifdef LOGIN_LIMIT
  1268.     /* check for exceeding max player limit */
  1269.     login_number++;
  1270.     if (under_limit && (login_number > MAX_LOGINS)) {
  1271.     under_limit = 0;
  1272.     fprintf(connlog_fp, 
  1273.         "Limit of %d players reached. Logins disabled.\n", 
  1274.         MAX_LOGINS);
  1275.     fflush(connlog_fp);
  1276.     }
  1277. #endif                /* LOGIN_LIMIT */
  1278.  
  1279.     /* give players a message on connection */
  1280.     if (!options.login_allow || !under_limit) {
  1281.     if (!options.login_allow) {
  1282.         fcache_dump(d, options.down_fcache);
  1283.         raw_notify(player, asterisk_line);
  1284.         if (cf_downmotd_msg && *cf_downmotd_msg)
  1285.         raw_notify(player, cf_downmotd_msg);
  1286.     } 
  1287. #ifdef LOGIN_LIMIT
  1288.     else if (!under_limit) {
  1289.         fcache_dump(d, options.full_fcache);
  1290.         raw_notify(player, asterisk_line);
  1291.         if (cf_fullmotd_msg && *cf_fullmotd_msg)
  1292.         raw_notify(player, cf_fullmotd_msg);
  1293.     }
  1294. #endif                /* LOGIN_LIMIT */
  1295.     if (!Can_Login(player)) {
  1296.         raw_notify(player, asterisk_line);
  1297.         /* even though the connection has been refused, we still want
  1298.          * to update the Last info on the player.
  1299.          */
  1300.         check_last(player, d->addr);
  1301.         return 0;
  1302.     } else
  1303.         raw_notify(player, asterisk_line);
  1304.     }
  1305.  
  1306.     /* give permanent text messages */
  1307.     if (new)
  1308.     fcache_dump(d, options.newuser_fcache);
  1309.     fcache_dump(d, options.motd_fcache);
  1310.     if (Hasprivs(player))
  1311.     fcache_dump(d, options.wizmotd_fcache);
  1312.  
  1313.     announce_connect(player);    /* broadcast connect message */
  1314.     check_last(player, d->addr); /* set Last, Lastsite, give paycheck */
  1315. #ifdef USE_MAILER
  1316.     if (!new)
  1317.     check_mail(player, 0);
  1318. #endif
  1319.     do_look_around(player);
  1320.     if (Haven(player)) {
  1321.     notify(player, "Your HAVEN flag is set. You cannot receive pages.");
  1322.     }
  1323.     return 1;
  1324. }
  1325.   
  1326. int check_connect(d, msg)
  1327.      struct descriptor_data *d;
  1328.      const char *msg;
  1329. {
  1330.     char command[MAX_COMMAND_LEN];
  1331.     char user[MAX_COMMAND_LEN];
  1332.     char password[MAX_COMMAND_LEN];
  1333.     dbref player;
  1334.  
  1335.     parse_connect(msg, command, user, password);
  1336.  
  1337.     if (!strncmp(command, "co", 2)) {
  1338.     if ((player = connect_player(user, password)) == NOTHING) {
  1339.         queue_string(d, connect_fail);
  1340.         do_log(LT_CONN, 0, 0, "[%d/%s] Failed connect to '%s'.",
  1341.            d->descriptor, d->addr, user);
  1342.     } else {
  1343.         do_log(LT_CONN, 0, 0, "[%d/%s] Connected to %s(#%d) in %s(#%d)",
  1344.            d->descriptor, d->addr, Name(player), player,
  1345.            Name(Location(player)), Location(player));
  1346.         if ((dump_messages(d, player, 0)) == 0)
  1347.         return 0;
  1348.     }
  1349.     } else if (!strncmp(command, "cr", 2)) {
  1350. #ifdef LOCKOUT
  1351.     if (forbidden_site(0, d->addr)) {
  1352.         fcache_dump(d, options.register_fcache);
  1353.         do_log(LT_CONN, 0, 0, "[%d/%s] Refused create for '%s'.",
  1354.            d->descriptor, d->addr, user);
  1355.         fflush(connlog_fp);
  1356.         return 0;
  1357.     }
  1358. #else
  1359. #ifdef WCREAT
  1360.     fcache_dump(d, options.register_fcache);
  1361.     return 1;
  1362. #endif                /* WCREAT */
  1363. #endif                /* LOCKOUT */
  1364.     if ((player = create_player(user, password, d->addr)) == NOTHING) {
  1365.         queue_string(d, create_fail);
  1366.         do_log(LT_CONN, 0, 0, "[%d/%s] Failed create for '%s'.",
  1367.            d->descriptor, d->addr, user);
  1368.     } else {
  1369.         do_log(LT_CONN, 0, 0, "[%d/%s] Created %s(#%d)",
  1370.            d->descriptor, d->addr, Name(player), player);
  1371.         if ((dump_messages(d, player, 1)) == 0)
  1372.         return 0;
  1373.     }                /* successful player creation */
  1374.     } else {
  1375.     /* invalid command, just repeat login screen */
  1376.     welcome_user(d);
  1377.     }
  1378.     fflush(connlog_fp);
  1379.     return 1;
  1380. }
  1381.  
  1382. void parse_connect(msg, command, user, pass)
  1383.     const char *msg;
  1384.     char *command;
  1385.     char *user;
  1386.     char *pass;
  1387. {
  1388.   char *p;
  1389.   while (*msg && isascii(*msg) && isspace(*msg))
  1390.     msg++;
  1391.   p = command;
  1392.   while (*msg && isascii(*msg) && !isspace(*msg))
  1393.     *p++ = *msg++;
  1394.   *p = '\0';
  1395.   while (*msg && isascii(*msg) && isspace(*msg))
  1396.     msg++;
  1397.   p = user;
  1398.   while (*msg && isascii(*msg) && !isspace(*msg))
  1399.     *p++ = *msg++;
  1400.   *p = '\0';
  1401.   while (*msg && isascii(*msg) && isspace(*msg))
  1402.     msg++;
  1403.   p = pass;
  1404.   while (*msg && isascii(*msg) && !isspace(*msg))
  1405.     *p++ = *msg++;
  1406.   *p = '\0';
  1407. }
  1408.  
  1409. void close_sockets()
  1410. {
  1411.   struct descriptor_data *d, *dnext;
  1412.  
  1413. #ifdef RWHO_SEND
  1414.   rwhocli_shutdown();
  1415. #endif
  1416.   for (d = descriptor_list; d; d = dnext) {
  1417.     dnext = d->next;
  1418.     write(d->descriptor, shutdown_message, strlen(shutdown_message));
  1419.     if (shutdown(d->descriptor, 2) < 0)
  1420.       perror("shutdown");
  1421.     close(d->descriptor);
  1422.   }
  1423. }
  1424.  
  1425. void emergency_shutdown()
  1426. {
  1427.   close_sockets();
  1428. }
  1429.  
  1430. void boot_off(player)
  1431.     dbref player;
  1432. {
  1433.   struct descriptor_data *d;
  1434.   for (d = descriptor_list; d; d = d->next) {
  1435.     if (d->connected && (d->player == player)) {
  1436.       shutdownsock(d);
  1437.       return;
  1438.     }
  1439.   }
  1440. }
  1441.  
  1442. void boot_desc(port)
  1443.      int port;
  1444. {
  1445.   struct descriptor_data *d;
  1446.   for (d = descriptor_list; (d); d = d->next) {
  1447.     if (d->descriptor == port) {
  1448.       shutdownsock(d);
  1449.       return;
  1450.     }
  1451.   }
  1452. }
  1453.  
  1454. dbref find_player_by_desc(port)
  1455.      int port;
  1456. {
  1457.   /* given a descriptor, find the matching player dbref */
  1458.  
  1459.   struct descriptor_data *d;
  1460.   for (d = descriptor_list; (d); d = d->next) {
  1461.     if (d->connected && (d->descriptor == port)) {
  1462.       return d->player;
  1463.     }
  1464.   }
  1465.  
  1466.   /* didn't find anything */
  1467.   return NOTHING;
  1468. }
  1469.  
  1470. int bailout(sig, code, scp)
  1471.     int sig;
  1472.     int code;
  1473.     struct sigcontext *scp;
  1474. {
  1475.   char tbuf1[BUFFER_LEN];
  1476.  
  1477.   sprintf(tbuf1, "BAILOUT: caught signal %d code %d", sig, code);
  1478.   panic(tbuf1);
  1479.   _exit(7);
  1480.   return 0;
  1481. }
  1482.  
  1483. void dump_users(call_by, match, doing)
  1484.     struct descriptor_data *call_by;
  1485.     char *match;
  1486.     int doing;         /* 0 if normal WHO, 1 if DOING */
  1487. {
  1488.   struct descriptor_data *d;
  1489.   int count = 0;
  1490.   time_t now;
  1491.   char tbuf1[BUFFER_LEN];
  1492.   char tbuf2[BUFFER_LEN];
  1493.  
  1494.   if(call_by->player < 0 || call_by->player >= db_top) {
  1495.       do_log(LT_ERR, 0, 0, "Bogus caller #%d of dump_users", call_by->player);
  1496.       return;
  1497.   }
  1498.   while(*match && *match == ' ') match++;
  1499.   now = time((time_t *) 0);
  1500.  
  1501. /* If a wizard/royal types "DOING" it gives him the normal player WHO,
  1502.  * BUT flags are not shown. Wizard/royal WHO does not show @doings.
  1503.  */
  1504.  
  1505.   if ((doing) || !Priv_Who(call_by->player)) {
  1506. #ifdef AT_DOING
  1507.     if (poll[0] == '\0')
  1508.       strcpy(poll, "Doing");
  1509.     sprintf(tbuf2,        "Player Name          On For   Idle  %s\n", poll);
  1510.     queue_string(call_by, tbuf2);
  1511. #else
  1512.     queue_string(call_by, "Player Name          On For   Idle\n");
  1513. #endif
  1514.   }
  1515.   else {
  1516.     queue_string(call_by,
  1517.          "Player Name     Room #    On For  Idle  Cmds  Des  Host\n");
  1518.   }
  1519.  
  1520.   for (d = descriptor_list; d; d = d->next) {
  1521.     if (d->connected) {
  1522.       if(d->player < 0 || d->player >= db_top) continue;
  1523.       if(!Hidden(d) || Priv_Who(call_by->player)) ++count;
  1524.       if (match && !(string_prefix(Name(d->player), match)))
  1525.     continue;
  1526.  
  1527.       if (call_by->connected && !(doing) && Priv_Who(call_by->player)) {
  1528.     sprintf(tbuf1, "%-16s %5d %9s %5s  %4d  %3d  %s",
  1529.         Name(d->player),
  1530.         Location(d->player),
  1531.         time_format_1(now - d->connected_at),
  1532.         time_format_2(now - d->last_time),
  1533.         d->cmds,
  1534.         d->descriptor,
  1535.         d->addr);
  1536.     if(Hidden(d))
  1537.         sprintf(tbuf1+strlen(tbuf1)," (Dark)");
  1538.       } else {
  1539.     if(!Hidden(d) || (Priv_Who(call_by->player) && (doing))) {
  1540. #ifdef AT_DOING
  1541.       sprintf(tbuf1, "%-16s %10s   %4s  %s",
  1542. #else
  1543.       sprintf(tbuf1, "%-16s %10s   %4s",
  1544. #endif
  1545.           Name(d->player),
  1546.           time_format_1(now - d->connected_at),
  1547.           time_format_2(now - d->last_time)
  1548. #ifdef AT_DOING
  1549.               , d->doing
  1550. #endif
  1551.           );
  1552.     }
  1553.       }
  1554.  
  1555.       if(!Hidden(d) || Priv_Who(call_by->player)) {
  1556.         queue_string(call_by, tbuf1);
  1557.         queue_write(call_by, "\n", 1);
  1558.       }
  1559.  
  1560.     }
  1561.  
  1562.  }
  1563.   sprintf(tbuf1, "There are %d players connected.\n", count);
  1564.   queue_string(call_by, tbuf1);
  1565. }
  1566.  
  1567. const char *time_format_1(dt)
  1568.     long dt;
  1569. {
  1570.   register struct tm *delta;
  1571.   static char buf[64];
  1572.   if (dt < 0)
  1573.     dt = 0;
  1574.  
  1575.   delta = gmtime((time_t *) &dt);
  1576.   if (delta->tm_yday > 0) {
  1577.     sprintf(buf, "%dd %02d:%02d",
  1578. /*    sprintf(buf, "%d:%02d:%02d", */
  1579.         delta->tm_yday, delta->tm_hour, delta->tm_min);
  1580.   } else {
  1581.     sprintf(buf, "%02d:%02d",
  1582.         delta->tm_hour, delta->tm_min);
  1583.   }
  1584.   return buf;
  1585. }
  1586.  
  1587. const char *time_format_2(dt)
  1588.     long dt;
  1589. {
  1590.   register struct tm *delta;
  1591.   static char buf[64];
  1592.   if (dt < 0)
  1593.     dt = 0;
  1594.  
  1595.   delta = gmtime((time_t *)&dt);
  1596.   if (delta->tm_yday > 0) {
  1597.     sprintf(buf, "%dd", delta->tm_yday);
  1598.   } else if (delta->tm_hour > 0) {
  1599.     sprintf(buf, "%dh", delta->tm_hour);
  1600.   } else if (delta->tm_min > 0) {
  1601.     sprintf(buf, "%dm", delta->tm_min);
  1602.   } else {
  1603.     sprintf(buf, "%ds", delta->tm_sec);
  1604.   }
  1605.   return buf;
  1606. }
  1607.  
  1608. void announce_connect(player)
  1609.     dbref player;
  1610. {
  1611.     dbref loc;
  1612.     ATTR *temp;
  1613.     char tbuf1[BUFFER_LEN];
  1614.     dbref zone;
  1615.     dbref obj;
  1616.     char *s;
  1617.     DESC *d;
  1618.     int num = 0;
  1619.     int hidden;
  1620.  
  1621. #if (CHAT_SYSTEM >= 2)
  1622.     int b, mask, chan;
  1623. #endif
  1624.  
  1625.     Toggles(player) |= PLAYER_CONNECT;
  1626.  
  1627.     hidden = Can_Hide(player) && (Flags(player) & DARK);
  1628.  
  1629.     /* send out RWHO stuff. We're going to use tbuf1 in a moment again */
  1630. #ifdef RWHO_SEND
  1631.     sprintf(tbuf1,"%d@%s", player, MUDNAME);
  1632.     rwhocli_userlogin(tbuf1, Name(player), time((time_t *) 0));
  1633. #endif
  1634.  
  1635.     /* check to see if this is a reconnect and also set DARK status */
  1636.     DESC_ITER_CONN(d) {
  1637.     if (d->player == player) {
  1638.         num++;
  1639.         if (hidden)
  1640.         d->hide = 1;
  1641.     }
  1642.     }
  1643.     
  1644.     if (num > 1)
  1645.     sprintf(tbuf1, "%s has reconnected.", Name(player));
  1646.     else
  1647.     sprintf(tbuf1, "%s has connected.", Name(player));
  1648.   
  1649.   /* send out messages */
  1650.   if (Suspect(player))
  1651.     raw_broadcast(WIZARD, "Broadcast: Suspect %s", tbuf1);
  1652.  
  1653.   toggle_broadcast(PLAYER_MONITOR, "GAME: %s", tbuf1);
  1654.  
  1655. #if (CHAT_SYSTEM >= 2)
  1656.   /* tell players on a channel when someone connects */
  1657.  
  1658.     mask = 1;
  1659.     chan = db[player].channels;
  1660.  
  1661.   /* Dark players only show up on privileged channels */
  1662.   if (!Dark(player)) {
  1663.       for (b = 1; b <= 32; b++) {
  1664.       if (chan & mask)
  1665.           channel_broadcast(mask, "<%s> %s", channel_name(mask), tbuf1);
  1666.       mask <<= 1;
  1667.       }
  1668.   } else {
  1669.       for (b = 1; b <= 32; b++) {
  1670.       if ((chan & mask) && (ChanPrivs(mask) != CHP_PUBLIC))
  1671.           channel_broadcast(mask, "<%s> %s", channel_name(mask), tbuf1);
  1672.       mask <<= 1;
  1673.       }
  1674.   }
  1675.  
  1676. #endif                /* CHAT_SYSTEM */
  1677.  
  1678.   if ((loc = getloc(player)) == NOTHING) {
  1679.     notify(player,"You are nowhere!");
  1680.     return;
  1681.   }
  1682.  
  1683.   speaker = player;
  1684.  
  1685.   raw_notify(player, asterisk_line);
  1686.   if(cf_motd_msg && *cf_motd_msg)
  1687.     raw_notify(player, cf_motd_msg);
  1688.   raw_notify(player, " ");
  1689.   if(Hasprivs(player) && cf_wizmotd_msg && *cf_wizmotd_msg)
  1690.     raw_notify(player, cf_wizmotd_msg);
  1691.   raw_notify(player, asterisk_line);
  1692.       
  1693.   notify_except(db[player].contents, player, tbuf1);
  1694.   /* added to allow player's inventory to hear a player connect */
  1695.  
  1696.   if(!Dark(player))
  1697.     notify_except(db[loc].contents, player, tbuf1);
  1698.  
  1699.   /* do the person's personal connect action */
  1700.   temp = atr_get(player, "ACONNECT");
  1701.   if (temp) {
  1702.     s = safe_uncompress(temp->value);
  1703.     parse_que(player, s, player);
  1704.     free(s);
  1705.   }
  1706.  
  1707. #ifdef GLOBAL_CONNECTS
  1708.   /* do the zone of the player's location's possible aconnect */
  1709.   if ((zone = getzone(loc)) != NOTHING) {
  1710.     switch (Typeof(zone)) {
  1711.     case TYPE_THING:
  1712.       temp = atr_get(zone, "ACONNECT");
  1713.       if (temp) {
  1714.     s = safe_uncompress(temp->value);
  1715.     parse_que(zone, s, player);
  1716.     free(s);
  1717.       }
  1718.       break;
  1719.     case TYPE_ROOM:
  1720.       /* check every object in the room for a connect action */
  1721.       DOLIST(obj, db[zone].contents) {
  1722.     temp = atr_get(obj, "ACONNECT");
  1723.     if (temp) {
  1724.       s = safe_uncompress(temp->value);
  1725.       parse_que(obj, s, player);
  1726.       free(s);
  1727.     }
  1728.       }
  1729.       break;
  1730.     default:
  1731.       do_log(LT_ERR, 0, 0, "Invalid zone #%d for %s(#%d) has bad type %d",
  1732.          zone, Name(player), player, Typeof(zone));
  1733.     }
  1734.   }
  1735.  
  1736.     /* now try the master room */
  1737. #ifdef DO_GLOBALS
  1738.     DOLIST(obj, db[MASTER_ROOM].contents) {
  1739.       temp = atr_get(obj, "ACONNECT");
  1740.       if (temp) {
  1741.     s = safe_uncompress(temp->value);
  1742.     parse_que(obj, s, player);
  1743.     free(s);
  1744.       }
  1745.     }
  1746. #endif /* DO_GLOBALS */
  1747. #endif /* GLOBAL_CONNECTS */
  1748.  
  1749. }
  1750.  
  1751. void announce_disconnect(player)
  1752.     dbref player;
  1753. {
  1754.   dbref loc;
  1755.   int num;
  1756.   ATTR *temp;
  1757.   struct descriptor_data *d;
  1758.   char tbuf1[BUFFER_LEN];
  1759.   dbref zone, obj;
  1760.   char *s, *p;
  1761.   time_t tt;
  1762.  
  1763. #if (CHAT_SYSTEM >= 2)
  1764.   int b, mask, chan;
  1765. #endif
  1766.  
  1767.   tt = time((time_t *) 0);
  1768.   p = ctime(&tt);
  1769.   p[strlen(p) - 1] = 0;
  1770.  
  1771.   if ((loc = getloc(player)) == NOTHING)
  1772.     return;
  1773.  
  1774.   speaker = player;
  1775.  
  1776.   for (num = 0, d = descriptor_list; d; d = d->next)
  1777.     if (d->connected && (d->player == player))
  1778.       num++;
  1779.   if (num < 2) {
  1780.  
  1781. #ifdef RWHO_SEND
  1782.     sprintf(tbuf1, "%d@%s", player, MUDNAME);
  1783.     rwhocli_userlogout(tbuf1);
  1784. #endif
  1785.  
  1786.     sprintf(tbuf1, "%s has disconnected.", Name(player));
  1787.  
  1788.     if(!Dark(player))
  1789.       notify_except(db[loc].contents, player, tbuf1);
  1790.     /* notify contents */
  1791.     notify_except(db[player].contents,player, tbuf1);
  1792.  
  1793.     temp = atr_get(player, "ADISCONNECT");
  1794.     if (temp) {
  1795.       s = safe_uncompress(temp->value);
  1796.       parse_que(player, s, player);
  1797.       free(s);
  1798.     }
  1799.  
  1800. #ifdef GLOBAL_CONNECTS
  1801.   /* do the zone of the player's location's possible adisconnect */
  1802.   if ((zone = getzone(loc)) != NOTHING) {
  1803.     switch (Typeof(zone)) {
  1804.     case TYPE_THING:
  1805.       temp = atr_get(zone, "ADISCONNECT");
  1806.       if (temp) {
  1807.     s = safe_uncompress(temp->value);
  1808.     parse_que(zone, s, player);
  1809.     free(s);
  1810.       }
  1811.       break;
  1812.     case TYPE_ROOM:
  1813.       /* check every object in the room for a connect action */
  1814.       DOLIST(obj, db[zone].contents) {
  1815.     temp = atr_get(obj, "ADISCONNECT");
  1816.     if (temp) {
  1817.       s = safe_uncompress(temp->value);
  1818.       parse_que(obj, s, player);
  1819.       free(s);
  1820.     }
  1821.       }
  1822.       break;
  1823.     default:
  1824.       do_log(LT_ERR, 0, 0, "Invalid zone #%d for %s(#%d) has bad type %d",
  1825.          zone, Name(player), player, Typeof(zone));
  1826.     }
  1827.   }
  1828.  
  1829.     /* now try the master room */
  1830. #ifdef DO_GLOBALS
  1831.     DOLIST(obj, db[MASTER_ROOM].contents) {
  1832.       temp = atr_get(obj, "ADISCONNECT");
  1833.       if (temp) {
  1834.     s = safe_uncompress(temp->value);
  1835.     parse_que(obj, s, player);
  1836.     free(s);
  1837.       }
  1838.     }
  1839. #endif /* DO_GLOBALS */
  1840.  
  1841. #endif /* GLOBAL_CONNECTS */
  1842.  
  1843.     Toggles(player) &= ~PLAYER_CONNECT;
  1844.  
  1845.     sprintf(tbuf1, "%s has disconnected.", Name(player));
  1846.   } else {
  1847.     /* note: when you partially disconnect, ADISCONNECTS are not executed */
  1848.     sprintf(tbuf1, "%s has partially disconnected.", Name(player));
  1849.  
  1850.     if(!Dark(player))
  1851.       notify_except(db[loc].contents, player, tbuf1);
  1852.     /* notify contents */
  1853.     notify_except(db[player].contents,player, tbuf1);
  1854.   }
  1855.   /* now print messages */
  1856.   if (Suspect(player))
  1857.     raw_broadcast(WIZARD, "Broadcast: Suspect %s", tbuf1);
  1858.  
  1859.   toggle_broadcast(PLAYER_MONITOR, "GAME: %s", tbuf1);
  1860.  
  1861. #if (CHAT_SYSTEM >= 2)
  1862.   /* tell players on channel that someone's left */
  1863.  
  1864.   mask = 1;
  1865.   chan = db[player].channels;
  1866.  
  1867.   /* Dark players only show up on priv'ed channels */
  1868.   if (!Dark(player)) {
  1869.       for (b = 1; b <= 32; b++) {
  1870.       if (chan & mask)
  1871.           channel_broadcast(mask, "<%s> %s", channel_name(mask), tbuf1);
  1872.       mask <<= 1;
  1873.       }
  1874.   } else {
  1875.       for (b = 1; b <= 32; b++) {
  1876.       if ((chan & mask) && (ChanPrivs(mask) != CHP_PUBLIC))
  1877.           channel_broadcast(mask, "<%s> %s", channel_name(mask), tbuf1);
  1878.       mask <<= 1;
  1879.       }
  1880.   }
  1881. #endif                /* CHAT_SYSTEM */
  1882. }
  1883.  
  1884. void do_motd(player, key, message)
  1885.      dbref player;
  1886.      int key;
  1887.      const char *message;
  1888. {
  1889.     
  1890.     if (!Wizard(player) && (key != 3)) {
  1891.     notify(player,
  1892.            "You may get 15 minutes of fame and glory in life, but not right now.");
  1893.     return;
  1894.     }
  1895.     
  1896.     switch(key) {
  1897.       case 1:
  1898.     strcpy(cf_motd_msg, message);
  1899.     notify(player, "Motd set.");
  1900.     break;
  1901.       case 2:
  1902.     strcpy(cf_wizmotd_msg, message);
  1903.     notify(player, "Wizard motd set.");
  1904.     break;
  1905.       case 4:
  1906.     strcpy(cf_downmotd_msg, message);
  1907.     notify(player, "Down motd set.");
  1908.     break;
  1909.       case 5:
  1910.     strcpy(cf_fullmotd_msg, message);
  1911.     notify(player, "Full motd set.");
  1912.     break;
  1913.       default:
  1914.     notify(player, tprintf("MOTD: %s", cf_motd_msg));
  1915.     if (Hasprivs(player)) {
  1916.         notify(player, tprintf("Wiz MOTD: %s", cf_wizmotd_msg));
  1917.         notify(player, tprintf("Down MOTD: %s", cf_downmotd_msg));
  1918.         notify(player, tprintf("Full MOTD: %s", cf_fullmotd_msg));
  1919.     }
  1920.     }
  1921. }
  1922.  
  1923. #ifdef AT_DOING
  1924. void do_doing(player, message)
  1925.      dbref player;
  1926.      const char *message;
  1927. {
  1928.    char buf[MAX_COMMAND_LEN];
  1929.    struct descriptor_data *d;
  1930.    int i;
  1931.  
  1932.    if (!Connected(player)) {
  1933.      /* non-connected things have no need for a doing */
  1934.      notify(player, "Why would you want to do that?");
  1935.      return;
  1936.    }
  1937.  
  1938.    strncpy(buf, message, 39);
  1939.  
  1940.    /* now smash undesirable characters and truncate */
  1941.    for (i = 0; i < 40; i++) {
  1942.      if ((buf[i] == '\r') || (buf[i] == '\n') || 
  1943.      (buf[i] == '\t') || (buf[i] == '\a'))
  1944.        buf[i] = ' ';
  1945.    }
  1946.    buf[39]='\0';
  1947.  
  1948.    /* set it */
  1949.    for (d = descriptor_list; d; d=d->next)
  1950.      if (d->connected && (d->player == player))
  1951.        strcpy(d->doing, buf);
  1952.    if (strlen(message) > 39)
  1953.      notify(player, 
  1954.         tprintf("Doing set. %d characters lost.", strlen(message) - 39));
  1955.    else
  1956.      notify(player, "Doing set.");
  1957. }
  1958.  
  1959. /* this sets the message which replaces "Doing" */
  1960. void do_poll(player, message)
  1961.      dbref player;
  1962.      const char *message;
  1963. {
  1964.  
  1965.   if (!Change_Poll(player)) {
  1966.     notify(player, "Who do you think you are, Gallup?");
  1967.     return;
  1968.   }
  1969.  
  1970.   strncpy(poll, message, 39);
  1971.   if (strlen(message) > 39)
  1972.     notify(player, 
  1973.        tprintf("Poll set. %d characters lost.", strlen(message) - 39));
  1974.   else
  1975.     notify(player, "Poll set.");
  1976.   do_log(LT_WIZ, player, NOTHING, "Poll Set to '%s'.", poll);
  1977.   fflush(wizlog_fp);
  1978. }
  1979. #endif                /* AT_DOING */
  1980.  
  1981. #ifdef RWHO_SEND
  1982. #ifdef FULL_RWHO
  1983. void dump_rusers(call_by)
  1984.   struct descriptor_data *call_by;
  1985. {
  1986.   struct sockaddr_in addr;
  1987.   struct hostent *hp;
  1988.   char *p;
  1989.   int fd;
  1990.   int red;
  1991.   char *srv = NULL;
  1992.   int portnum = RWHOPORT;
  1993.   char tbuf1[BUFFER_LEN];
  1994.  
  1995.   p = srv = (char *)RWHOSERV;
  1996.   while (*p != '\0' && (*p == '.' || isdigit(*p)))
  1997.     p++;
  1998.  
  1999.   if(*p != '\0') {
  2000.     if((hp = gethostbyname(srv)) == (struct hostent *)0) {
  2001.     do_log(LT_ERR, 0, 0, "Unknown RWHO host %s", srv);
  2002.     queue_string(call_by,"Error in connecting to the RWHO server.\n");
  2003.     return;
  2004.      }
  2005.      (void)bcopy(hp->h_addr,(char *)&addr.sin_addr,hp->h_length);
  2006.   } else {
  2007.     unsigned long   f;
  2008.  
  2009.     if((f = inet_addr(srv)) == -1L) {
  2010.     do_log(LT_ERR, 0, 0, "Unknown RWHO host %s", srv);
  2011.     queue_string(call_by,"Error in connecting to the RWHO server.\n");
  2012.     return;
  2013.     }
  2014.     (void)bcopy((char *)&f,(char *)&addr.sin_addr,sizeof(f));
  2015.   }
  2016.   addr.sin_port = htons(portnum);
  2017.   addr.sin_family = AF_INET;
  2018.  
  2019.   if((fd = socket(AF_INET,SOCK_STREAM,0)) < 0) {
  2020.     queue_string(call_by, "Socket error in connecting to rwhod. sorry.\n");
  2021.     return;
  2022.   }
  2023.  
  2024.   if(connect(fd,&addr,sizeof(addr)) < 0) {
  2025.     queue_string(call_by, "Connect error in connecting to rwhod. sorry.\n");
  2026.     return;
  2027.   }
  2028.  
  2029.   while((red = read(fd, tbuf1, sizeof(tbuf1))) > 0)
  2030.     queue_write(call_by, tbuf1, red);
  2031.  
  2032.   close(fd);
  2033. }
  2034. #endif /*FULL_RWHO*/
  2035.  
  2036. void rwho_update()
  2037. {
  2038.   struct descriptor_data *d;
  2039.   char tbuf1[BUFFER_LEN];
  2040.  
  2041.   rwhocli_pingalive();
  2042.   for (d = descriptor_list; d; d= d->next) {
  2043.     if(d->connected && !Hidden(d)) {
  2044.       sprintf(tbuf1, "%d@%s", d->player, MUDNAME);
  2045.       rwhocli_userlogin(tbuf1, Name(d->player), d->connected_at);
  2046.     }
  2047.   }
  2048. }
  2049. #endif /* RWHO_SEND */
  2050.  
  2051. #ifdef LOCKOUT
  2052. int quick_wild(s, d)
  2053.     char *s;
  2054.     char *d;
  2055. {
  2056.   switch(*s) {
  2057.     case '?':
  2058.        return(wild(s+1, (*d) ? d+1 : d));
  2059.     case '*':
  2060.        return(wild(s+1, d) || ((*d) ? wild(s,d+1) : 0));
  2061.     default:
  2062.        return((UPCASE(*s) != UPCASE(*d)) ? 0 : ((*s) ? wild(s+1,d+1) : 1));
  2063.   }
  2064. }
  2065.  
  2066. int site_match(site, match)
  2067.      const char *site, *match;
  2068. {
  2069.   if (*match == '\0')
  2070.     return 0;
  2071.   while(match && *match) {
  2072.     switch (*match) {
  2073.     case '*':
  2074.       match++;
  2075.       while ((*site) && (*site != '.') && (*site != '\0'))
  2076.     site++;
  2077.       break;
  2078.     case '?':
  2079.       match++;
  2080.       site++;
  2081.       break;
  2082.     default:
  2083.       if (UPCASE(*match) != UPCASE(*site))
  2084.     return 0;
  2085.       site++;
  2086.       match++;
  2087.     }
  2088.   }
  2089.   return 1;
  2090. }
  2091.  
  2092. int forbidden_site(flag, hname)
  2093.   int flag;            /* 0 for registration, 1 for lockout */
  2094.   const char *hname;
  2095. {
  2096.   char buf[MAXHOSTNAMELEN], *newlin, *ptr;
  2097.   FILE *fp;
  2098.  
  2099.   if (flag)
  2100.     fp = fopen(LOCKOUT_FILE, "r");
  2101.   else
  2102.     fp = fopen(REGISTER_FILE, "r");
  2103.   while ((fp != NULL) && (!feof(fp))) {
  2104.     fgets(buf, MAXHOSTNAMELEN, fp);
  2105.     /* step on the newline */
  2106.     if ((newlin = (char *) index(buf, '\n')) != NULL) *newlin = '\0';
  2107.     ptr = buf;
  2108.     if (site_match(hname, ptr)) {
  2109.       fclose(fp);
  2110.       return 1;
  2111.     }
  2112.   }
  2113.   fclose(fp);
  2114.   return 0;
  2115. }
  2116. #endif /* LOCKOUT */
  2117.  
  2118. #ifdef NEVER
  2119. const char *addrout(a)
  2120.   long a;
  2121. {
  2122.   static char buf[MAXHOSTNAMELEN];
  2123.  
  2124.   struct hostent *he;
  2125.  
  2126.   he = gethostbyaddr(&a, sizeof(a), AF_INET);
  2127.   if (he) {
  2128.     return he->h_name;
  2129.   } else {
  2130.     a = ntohl(a);
  2131.     sprintf (buf, "%d.%d.%d.%d", (a >> 24) & 0xff, (a >> 16) & 0xff,
  2132.          (a >> 8) & 0xff, a & 0xff);
  2133.     return buf;
  2134.   }
  2135. }
  2136. #endif
  2137.  
  2138. const char *hostname_convert(nums)
  2139.      struct in_addr nums;
  2140. {
  2141.   /* given an address, convert it to either IP numbers or a hostname */
  2142.  
  2143.   struct hostent *he;
  2144.  
  2145.   he = gethostbyaddr((const char *)&nums.s_addr, sizeof(nums.s_addr), AF_INET);
  2146.   if (he == NULL)
  2147.     return ((char *)inet_ntoa(nums));   /* IP numbers */
  2148.   else
  2149.     return ((char *)he->h_name);        /* hostname */
  2150. }
  2151.  
  2152. dbref short_page(match)
  2153.   const char *match;
  2154. {
  2155.   /* attempts to match to the partial name of a connected player */
  2156.  
  2157.   struct descriptor_data *d;
  2158.   dbref who1 = NOTHING;
  2159.   int count = 0;
  2160.  
  2161.   for(d = descriptor_list; d; d = d->next) {
  2162.     if(d->connected) {
  2163.       if (match && !string_prefix(Name(d->player), match))
  2164.         continue;
  2165.       if (!strcasecmp(Name(d->player), match)) {
  2166.     count = 1;
  2167.     who1 = d->player;
  2168.     break;
  2169.       }
  2170.       who1 = d->player;
  2171.       count++;
  2172.     }
  2173.   }
  2174.  
  2175.   if(count > 1)
  2176.     return AMBIGUOUS;
  2177.   else if (count == 0)
  2178.     return NOTHING;
  2179.  
  2180.   return who1;
  2181. }
  2182.  
  2183.  
  2184. /* LWHO() function - really belongs in eval.c but needs stuff declared here */
  2185.  
  2186. XFUNCTION(fun_lwho)
  2187. {
  2188.   struct descriptor_data *d;
  2189.   char tbuf1[SBUF_LEN];
  2190.   char *bp;
  2191.  
  2192.   *buff = '\0';
  2193.   bp = buff;
  2194.  
  2195.   DESC_ITER_CONN(d) {
  2196.     if (!Hidden(d) || Priv_Who(privs)) {
  2197.       if (*buff)
  2198.     sprintf(tbuf1, " #%d", d->player);
  2199.       else
  2200.     sprintf(tbuf1, "#%d", d->player);
  2201.       safe_str(tbuf1, buff, &bp);
  2202.     }
  2203.   }
  2204.  
  2205.   *bp = '\0';
  2206. }
  2207.  
  2208. XFUNCTION(fun_idlesecs)
  2209. {
  2210.     /* returns the number of seconds a player has been idle */
  2211.  
  2212.     time_t now;
  2213.     struct descriptor_data *d;
  2214.     dbref target;
  2215.  
  2216.     now = time((time_t *) 0);
  2217.  
  2218.     target = lookup_player(args[0]);
  2219.     if (target == NOTHING) {
  2220.     init_match(privs, args[0], TYPE_PLAYER);
  2221.     match_absolute();
  2222.     match_player();
  2223.     target = match_result();
  2224.     }
  2225.  
  2226.     /* non-connected players return error -1 */
  2227.     if ((target == NOTHING) || !Connected(target)) {
  2228.     strcpy(buff, "-1");
  2229.     return;
  2230.     }
  2231.  
  2232.     /* else walk the descriptor list looking for a match */
  2233.     DESC_ITER_CONN(d) {
  2234.     if (d->player == target) {
  2235.         if (!Hidden(d) || Priv_Who(privs))
  2236.         sprintf(buff, "%d", (now - d->last_time));
  2237.         else
  2238.         strcpy(buff, "-1");
  2239.         return;
  2240.     }
  2241.     }
  2242.  
  2243.     /* if we hit this point we are in trouble */
  2244.     strcpy(buff, "-1");
  2245.     do_log(LT_ERR, 0, 0, 
  2246.        "Whoa. idlesecs() can't find player #%d on call by #%d\n",
  2247.         target, privs);
  2248. }
  2249.  
  2250. XFUNCTION(fun_conn)
  2251. {
  2252.     /* returns the number of seconds a player has been connected */
  2253.  
  2254.     time_t now;
  2255.     struct descriptor_data *d;
  2256.     dbref target;
  2257.  
  2258.     now = time((time_t *) 0);
  2259.  
  2260.     target = lookup_player(args[0]);
  2261.     if (target == NOTHING) {
  2262.     init_match(privs, args[0], TYPE_PLAYER);
  2263.     match_absolute();
  2264.     match_player();
  2265.     target = match_result();
  2266.     }
  2267.  
  2268.     /* non-connected players and dark wizards return error, -1 */
  2269.     if ((target == NOTHING) || !Connected(target)) {
  2270.     strcpy(buff, "-1");
  2271.     return;
  2272.     }
  2273.  
  2274.     /* else walk the descriptor list looking for a match */
  2275.     DESC_ITER_CONN(d) {
  2276.     if (d->player == target) {
  2277.         if (!Hidden(d) || Priv_Who(privs)) 
  2278.         sprintf(buff, "%d", (now - d->connected_at));
  2279.         else
  2280.         strcpy(buff, "-1");
  2281.         return;
  2282.     }
  2283.     }
  2284.  
  2285.     /* if we hit this point we are in trouble */
  2286.     strcpy(buff, "-1");
  2287.     do_log(LT_ERR, 0, 0, "Whoa. conn() can't find player #%d on call by #%d\n",
  2288.         target, privs);
  2289. }
  2290.  
  2291. void hide_player(player, hide)
  2292.      dbref player;
  2293.      int hide;            /* hide player? */
  2294. {
  2295.     DESC *d;
  2296. #ifdef RWHO_SEND
  2297.     char buf[BUFFER_LEN];
  2298. #endif
  2299.  
  2300.     if (!Connected(player))
  2301.     return;
  2302.  
  2303.     if (!Can_Hide(player)) {
  2304.     notify(player, "Permission denied.");
  2305.     return;
  2306.     }
  2307.  
  2308.     /* change status on WHO */
  2309.  
  2310.     if (Can_Hide(player)) {
  2311.     DESC_ITER_CONN(d) {
  2312.         if (d->player == player)
  2313.         d->hide = hide;
  2314.     }
  2315.     }
  2316.  
  2317.     /* change status on RWHO if necessary */
  2318.  
  2319. #ifdef RWHO_SEND
  2320.     sprintf(buf, "%d@%s", player, MUDNAME);
  2321.     if (hide)
  2322.     rwhocli_userlogout(buf);
  2323.     else
  2324.     rwhocli_userlogin(buf, Name(player), time((time_t *)NULL));
  2325. #endif
  2326. }
  2327.  
  2328. #ifdef IDLE_TIMEOUT
  2329. void inactivity_check()
  2330. {
  2331.   DESC *d;
  2332.   register struct tm *idle;
  2333.   time_t now;
  2334.   int check, hrs, mns;
  2335.   check = hrs = mns = 0;
  2336.   now = time((time_t *) 0);
  2337.  
  2338.   for (mns = INACTIVITY_LIMIT; mns > 60; mns -= 60, hrs++)
  2339.     ;
  2340.  
  2341.   DESC_ITER_CONN(d) {
  2342.  
  2343.     check = (now - d->last_time);
  2344.     idle = gmtime((time_t *) &check);
  2345.  
  2346.     if ((idle->tm_hour > hrs) ||
  2347.     ((idle->tm_hour == hrs) && (idle->tm_min >= mns))) {
  2348.  
  2349.       if (!Can_Idle(d->player)) {
  2350.  
  2351.     notify(d->player, "\n*** Inactivity timeout ***\n");
  2352.     do_log(LT_CONN, 0, 0, "[%d/%s] Logout by %s(#%d) <Inactivity Timeout>",
  2353.            d->descriptor, d->addr, Name(d->player), d->player);
  2354.     fflush(connlog_fp);
  2355.     boot_off(d->player);
  2356.  
  2357.       } else if (Unfind(d->player)) {
  2358.  
  2359.     if (Can_Hide(d->player)) {
  2360.       notify(d->player, 
  2361.          "\n*** Inactivity limit reached. You are now DARK. ***\n");
  2362.       Flags(d->player) |= DARK;
  2363.     } else {
  2364.       notify(d->player, "\n*** Inactivity limit reached. ***\n");
  2365.     }
  2366.       }
  2367.     }
  2368.   }
  2369. }
  2370.  
  2371. #endif                /* IDLE_TIMEOUT */
  2372.  
  2373.  
  2374. #if (CHAT_SYSTEM >= 2)
  2375. void channel_broadcast(channel, va_alist)
  2376.      channel_type channel;
  2377.      va_dcl
  2378. {
  2379.   va_list args;
  2380.   char *fmt;
  2381.   char tbuf1[BUFFER_LEN];
  2382.   DESC *d;
  2383.  
  2384.   /* Make sure we can write to the channel before doing so */
  2385.   if (ChanPrivs(channel) == CHP_FORBID)
  2386.       return;
  2387.  
  2388.   va_start(args);
  2389.   fmt = va_arg(args, char *);
  2390.   
  2391.   (void) vsprintf(tbuf1, fmt, args);
  2392.  
  2393.   DESC_ITER_CONN(d) {
  2394.     if ((db[d->player].channels & channel) == channel) {
  2395.       queue_string(d, tbuf1);
  2396.       queue_write(d, "\n", 1);
  2397.       process_output(d);
  2398.     }
  2399.   }
  2400. }
  2401.  
  2402. void do_channel_who(player, chan)
  2403.      dbref player;
  2404.      channel_type chan;
  2405. {
  2406.   DESC *d;
  2407.   char tbuf1[BUFFER_LEN];
  2408.   tbuf1[0] = '\0';
  2409.  
  2410.   DESC_ITER_CONN(d) {
  2411.     if (((db[d->player].channels & chan) == chan) &&
  2412.     (!Dark(d->player) || Priv_Who(player))) {
  2413.       if (tbuf1[0] == '\0')    /* beginning of list */
  2414.     sprintf(tbuf1, "%s", Name(d->player));
  2415.       else if ((strlen(tbuf1) + PLAYER_NAME_LIMIT) < BUFFER_LEN)
  2416.     sprintf(tbuf1, "%s, %s", tbuf1, Name(d->player));
  2417.     }
  2418.   }
  2419.  
  2420.   if (tbuf1[0] == '\0')
  2421.     notify(player, "There are no connected players on that channel.");
  2422.   else {
  2423.     notify(player, "Connected players on that channel are:");
  2424.     notify(player, tbuf1);
  2425.   }
  2426. }
  2427. #endif                /* CHAT_SYSTEM */
  2428.